package tau.adx.common.adn.impl;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import tau.adx.common.adn.AdNetwork;
import tau.adx.common.advertisers.Advertiser;
import tau.adx.common.bids.bundles.AdxBidBundle;
import tau.adx.common.bids.generators.SimpleBidBundleGenerator;
import tau.adx.common.contracts.MonthlyContract;
import tau.adx.common.messages.contracts.MonthlyContractRegisterd;
import tau.adx.common.messages.time.NewMonth;
import tau.adx.common.users.generators.SimpleUserGenerator;
import tau.adx.simulator.AdX;

import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;

/**
 * A simple implemetation of an {@link AdNetwork}. {@link AdxBidBundle Bid
 * bundles} are generated randomly.
 * 
 * @author greenwald
 * 
 */
@Data
@EqualsAndHashCode(exclude = "monthlyContracts")
@ToString(exclude = "monthlyContracts")
public class SimpleAdNetwork implements AdNetwork {

	/**
	 * A {@link Set} of {@link MonthlyContract monthly contracts} registered to
	 * the {@link AdNetwork}.
	 */
	private Set<MonthlyContract> monthlyContracts = new HashSet<>();

	/**
	 * Ad network's name.
	 */
	private String name;

	/**
	 * @param name
	 *            The network's name.
	 */
	public SimpleAdNetwork(String name) {
		this.name = name;
		AdX.eventBus.register(this);
	}

	/**
	 * @see tau.adx.common.adn.AdNetwork#getNextDailyBidBundles()
	 */
	@Override
	public Map<Advertiser, AdxBidBundle> getNextDailyBidBundles() {

		SimpleBidBundleGenerator bundleGenerator = new SimpleBidBundleGenerator(
				SimpleUserGenerator.generateAllPossibleUsers(), AdX
						.getInstance().getPublishers(), false);
		Map<Advertiser, AdxBidBundle> advertiserToBundleMap = new HashMap<Advertiser, AdxBidBundle>();
		for (MonthlyContract monthlyContract : monthlyContracts) {
			advertiserToBundleMap.put(monthlyContract.getAdvertiser(),
					(AdxBidBundle) bundleGenerator.generate(1).toArray()[0]);
		}
		return advertiserToBundleMap;
	}

	/**
	 * Subscription method for the {@link EventBus}.
	 * 
	 * @param newMonth
	 *            {@link NewMonth} notiifcation message.
	 */
	@Subscribe
	public void newMonth(NewMonth newMonth) {
		monthlyContracts.clear();
	}

	/**
	 * @see tau.adx.common.adn.AdNetwork#registerMonthlyContract(tau.adx.common.contracts.MonthlyContract)
	 */
	@Override
	public void registerMonthlyContract(MonthlyContract monthlyContract) {
		monthlyContracts.add(monthlyContract);
		monthlyContract.setAdNetwork(this);
		AdX.eventBus.post(new MonthlyContractRegisterd(this, monthlyContract));
	}

}
